闲扯
不愧是一道省选题,感觉做着还是很有难度的。
题面
Solution
我们先把题意简化出来。
给出一序列,有以下两个操作:
- 给区间 $[l,r]$ 内的每一个数加上 $d$ 。
- 询问长度在 $[l,r]$ 之间的连续子序列的权值和。
设 $sum_k=\sum_{i=1}^k val_i$ ,那么我们要求的东西就是
我们设 $s_k=\sum_{i=1}^k sum_i$ 。
那么我们最终要求的东西就是
这个我们用线段树来维护,即可将单次询问的时间复杂度降低至 $O(\log n)$ 。
然后考虑区间加的时候,每一个 $s_k$ 会怎么变。
设 $f(i)=\frac{i\cdot (i+1)}{2}$ 。
简单画个图,推一下,可以发现:
- 对于 $\forall k\in[l,r]$ ,我们有 $s_k+=f(k-l+1)\cdot d$ 。
- 对于 $\forall k\in(r+1,n]$ ,我们有 $s_k+=f(r-l+1)\cdot d+d\cdot (r-l+1)\cdot (k-r)$ 。
考虑怎么用线段树维护这个式子。
对于 $k\in[l,r]$ ,我们有 $s_k+=\frac{k^2+(3-2l)k+(l^2-3l+2)}{2}\cdot d$ 。
对于 $k\in(r,n]$ ,我们有 $s_k+=(r-l+1)d+(r-l+1)(\frac{r-l+2}{2}-r)$ 。
所以我们分别维护出 $\sum i^2,\sum i,1$ 的懒标记即可。
Code
1 |
|